#include <cstring>
#include "ADecoder.h"
#include "Util/logc.h"

namespace Media{
ADecoder::ADecoder(int channel){
    m_channel = channel;
}
ADecoder::~ADecoder(){

}

bool ADecoder::InputFrame(const FrameCommon::Frame::Ptr& frame){
    if(!m_audioDecoder){
        AudioDecDesc decDesc;
        decDesc.card = 0;
        decDesc.channel = m_channel;
        if(createAudioDecoder(&decDesc, &m_audioDecoder) != 0){
            errorf("createAudioDecoder fail");
            return false;
        }

        AudioDecFormat format;
        memset(&format, 0, sizeof(AudioDecFormat));
        if(frame->codecId() == FrameCommon::AAC){
            format.type = audioEncAAC;
        }else if(frame->codecId() == FrameCommon::G711A){
            format.type = audioEncG711A;
        }else{
            errorf("unsupport codec type");
            m_audioDecoder->release(m_audioDecoder);
            m_audioDecoder = nullptr;
            return false;
        }
        
        m_audioDecoder->setFormat(m_audioDecoder, &format);

        // m_audioDecoder->setFrameCb(m_audioDecoder, [](void *frame, void *arg){
        //     ADecoder *dthis = (ADecoder *)arg;
        //     if(dthis){
        //         dthis->frameProc(frame);
        //     }
        // }, this);

        if(m_audioDecoder->start(m_audioDecoder) != 0){
            errorf("video decoder start fail");
            // m_audioDecoder->release(m_videoDecoder);
            m_audioDecoder = nullptr;
            return false;
        }

    }
        
    AudioDecPacket packet;
    packet.buffer = (uchar *)frame->data();
    packet.length = frame->size();

    m_audioDecoder->putPacket(m_audioDecoder, &packet);

    return true;
}
ADecoder::FrameConsumerId ADecoder::AddConsumer(std::function<void (const AVFrame::Ptr&)> consumer){
    tracef("VDecoder  AddConsumer");
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    m_frameConsumerIndex++;
    FrameConsumerId id = m_frameConsumerIndex;
    m_frameConsumers[id] = consumer;
    return id;
}

bool ADecoder::RemoveConsumer(FrameConsumerId id){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_frameConsumers.find(id) == m_frameConsumers.end()){
        return false;
    }
    m_frameConsumers.erase(id);
    return true;
}

int ADecoder::GetChannel(){

    return m_channel;
}

void ADecoder::ReleaseFrame(void *frame){
    // if(m_audioDecoder)
    //     m_audioDecoder->releaseFrame(m_audioDecoder, frame);
}

void ADecoder::frameProc(void *frame){
    std::weak_ptr<ADecoder> wptr = shared_from_this();
    auto ptr = std::make_shared<AVFrame>(frame, true, [wptr](void *frame){
        auto vptr = wptr.lock();
        if(vptr){
            vptr->ReleaseFrame(frame);
        }
    });

    std::lock_guard<std::recursive_mutex> guard(m_mux);
    for(auto [_, value]: m_frameConsumers){
        value(ptr);
    }
}

bool ADecoder::Start(){

    return true;
}

bool ADecoder::Stop(){

    return true;
}

}